using System;
using System.Collections.Generic;
using System.Text;
using GraphConstructor;

namespace PhoneNetwork.AntColony
{
    public class Pheromone
    {
        private Node _node;
        private double _probablilty;

        public double Probablilty
        {
            get { return _probablilty; }
            set { _probablilty = value; }
        }
        public Node Node
        {
            get { return _node; }
            set { _node = value; }
        }
        public Pheromone()
        {
        }
        public Pheromone(Node parent)
        {
            _node = parent;
        }
    }
    public class PheromoneTable
    {
        private Dictionary<Node, Pheromone> _entries;
        private Node _parent;

	    public Node Parent
	    {
		    get { return _parent;}
		    set { _parent = value;}
	    }
        public Dictionary<Node, Pheromone> Entries
        {
            get { return _entries; }
            set { _entries = value; }
        }
        public PheromoneTable()
        {
            _entries = new Dictionary<Node, Pheromone>();
        }

        // Constructor takes a node to represent and a list of all connected nodes off the
        // calling node
        public PheromoneTable(Node n, List<Edge> Connections)
        {
            _parent = n;

            // create a tableEntry array the same length as the number of connections
            _entries = new Dictionary<Node, Pheromone>(Connections.Count);

            // create a new tableEntry for each connection
            foreach (Edge edge in Connections)
            {
                _entries[edge.NodeTo] = new Pheromone(edge.NodeTo);
                _entries[edge.NodeTo].Probablilty = (100 / (double)Connections.Count);
            }

            // set default equal values
            //foreach (Pheromone pheromone in _entries.Values)  
        }
        public Node ProbablePath(List<Node> VisitedNodes)
        {
            // create a random generator
            Random r = new Random(Environment.TickCount);

            double val = 0;
            double count = 0;
            double Lastcount = -1;

            LinkedList<Node> tempTEVector = new LinkedList<Node>();
            foreach (Node node in _entries.Keys)
                if (!VisitedNodes.Contains(node))
                    // if the node is accepting connections
                    if (node.Value != 0)
                        // add the node as a possible candidate
                        tempTEVector.AddLast(node);

            // if all connections have been visited
            if (tempTEVector.Count == 0)
                // loop through all the connected nodes
                foreach (Node n in _entries.Keys)
                    tempTEVector.AddLast(n);

            // get the ceiling amount for probabilities
            foreach (Node node in tempTEVector)
                val += (_entries[node]).Probablilty;

            //create random value
            val = r.NextDouble() * val;

            // loop through the temp Table Entryies
            foreach (Node node in tempTEVector)
            {
                // increment the count on each loop
                count += (_entries[node]).Probablilty;

                // if the random value falls into delegated range then select that path as the next node
                if (val > Lastcount && val < count)
                    return node;

                // get the value of the last count
                Lastcount = count;
            }

            // method should never return here
            return null;
        }

        // updates the probabilities of the pheromone table by multiplying the selected 
        // nodes probability by a radio of  newVal
        public void UpdateProbabilities(double newVal, Node ChosenNode)
        {
            Pheromone pheromone;
            double total = 0;

            // loop through all the table entries
            // get the total enumeration of probabilities and add the new value.
            // Since this total will be more than 100 a ratio multiplication is
            // applied. Although these values will not equate to exactly 100% floating
            // point calculations will be accurate enough at least 99.99999% which is satisfactory
            foreach (Node node in _entries.Keys)
            {
                pheromone = _entries[node];
                // enumerate the total probablility
                total += pheromone.Probablilty;

                // if the table entry matches the id of the chosen node path
                if (ChosenNode == pheromone.Node)
                {
                    // add the new value to the total
                    total += newVal;
                    // add the new value the current value of the selected path
                    pheromone.Probablilty += newVal;
                }
            }

            // calculate the ratio for the multiplcation
            double ratio = 100 / total;

            // loop through each table entry and multiple the current probability
            // by the new ratio
            foreach(Pheromone p in _entries.Values)
                p.Probablilty *= ratio;

            // this will enumerate all the values to 99.99999%
        }
    }
}
